home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / cpp.arc / CPP4.C < prev    next >
C/C++ Source or Header  |  1985-11-27  |  27KB  |  792 lines

  1.  
  2. /*
  3.  *                          C P P 4 . C
  4.  *              M a c r o  D e f i n i t i o n s
  5.  *
  6.  * Edit History
  7.  * 31-Aug-84    MM      USENET net.sources release
  8.  * 04-Oct-84    MM      __LINE__ and __FILE__ must call ungetstring()
  9.  *                      so they work correctly with token concatenation.
  10.  *                      Added string formal recognition.
  11.  * 25-Oct-84    MM      "Short-circuit" evaluate #if's so that we
  12.  *                      don't print unnecessary error messages for
  13.  *                      #if !defined(FOO) && FOO != 0 && 10 / FOO ...
  14.  * 31-Oct-84    ado/MM  Added token concatenation
  15.  *  6-Nov-84    MM      Split off eval stuff
  16.  *  1-Apr-85    ado     Fixed bug in STRING_FORMAL version
  17.  *  2-May-85    MM      Changed the way macro parameters work -- only
  18.  *                      one byte is reserved, 255 param's possible.
  19.  */
  20.  
  21. #include        <stdio.h>
  22. #include        <ctype.h>
  23. #include        "cppdef.h"
  24. #include        "cpp.h"
  25. #if OK_CONCAT == CON_NOEXPAND
  26. #define SEP     COM_SEP                 /* concat token, don't reexpand */
  27. #endif
  28. #if OK_CONCAT == CON_EXPAND
  29. #define SEP     TOK_SEP                 /* concat token and reexpand    */
  30. #endif
  31.  
  32. /*
  33.  * parm[], parmp, and parlist[] are used to store #define() argument
  34.  * lists.  nargs contains the actual number of parameters stored.
  35.  */
  36. static char     parm[NPARMWORK + 1];    /* define param work buffer     */
  37. static char     *parmp;                 /* Free space in parm           */
  38. static char     *parlist[NMACPARS];     /* -> start of each parameter   */
  39. static int      nargs;                  /* Parameters for this macro    */
  40.  
  41. dodefine()
  42. /*
  43.  * Called from control when a #define is scanned.  This module
  44.  * parses formal parameters and the replacement string.  When
  45.  * the formal parameter name is encountered in the replacement
  46.  * string, it is replaced by a character in the range 128 to
  47.  * 128+NPARAM (this allows up to 32 parameters within the
  48.  * Dec Multinational range).  If cpp is ported to an EBCDIC
  49.  * machine, you will have to make other arrangements.
  50.  *
  51.  * There is some special case code to distinguish
  52.  *      #define foo     bar
  53.  * from #define foo()   bar
  54.  *
  55.  * Also, we make sure that
  56.  *      #define foo     foo
  57.  * expands to "foo" but doesn't put cpp into an infinite loop.
  58.  *
  59.  * A warning message is printed if you redefine a symbol to a
  60.  * different text.  I.e,
  61.  *      #define foo     123
  62.  *      #define foo     123
  63.  * is ok, but
  64.  *      #define foo     123
  65.  *      #define foo     +123
  66.  * is not.
  67.  *
  68.  * The following subroutines are called from define():
  69.  * checkparm    called when a token is scanned.  It checks through the
  70.  *              array of formal parameters.  If a match is found, the
  71.  *              token is replaced by a control byte which will be used
  72.  *              to locate the parameter when the macro is expanded.
  73.  * textput      puts a string in the macro work area (parm[]), updating
  74.  *              parmp to point to the first free byte in parm[].
  75.  *              textput() tests for work buffer overflow.
  76.  * charput      puts a single character in the macro work area (parm[])
  77.  *              in a manner analogous to textput().
  78.  */
  79. {
  80.         register int            c;
  81.         register DEFBUF         *dp;            /* -> new definition    */
  82.         int                     isredefine;     /* TRUE if redefined    */
  83.         char                    *old;           /* Remember redefined   */
  84.         extern int              save();         /* Save char in work[]  */
  85.  
  86.         if (type[(c = skipws())] != LET)
  87.             goto bad_define;
  88.         isredefine = FALSE;                     /* Set if redefining    */
  89.         if ((dp = lookid(c)) == NULL)           /* If not known now     */
  90.             dp = defendel(token, FALSE);        /* Save the name        */
  91.         else {                                  /* It's known:          */
  92.             isredefine = TRUE;                  /* Remember this fact   */
  93.             old = dp->repl;                     /* Remember replacement */
  94.             dp->repl = NULL;                    /* No replacement now   */
  95.         }
  96.         parlist[0] = parmp = parm;              /* Setup parm buffer    */
  97.         if ((c = get()) == '(') {               /* With arguments?      */
  98.             nargs = 0;                          /* Init formals counter */
  99.             do {                                /* Collect formal parms */
  100.                 if (nargs >= NMACPARS)
  101.                     cfatal("Too many arguments for macro", NULLST);
  102.                 else if ((c = skipws()) == ')')
  103.                     break;                      /* Got them all         */
  104.                 else if (type[c] != LET)        /* Bad formal syntax    */
  105.                     goto bad_define;
  106.                 scanid(c);                      /* Get the formal param */
  107.                 parlist[nargs++] = parmp;       /* Save its start       */
  108.                 textput(token);                 /* Save text in parm[]  */
  109.             } while ((c = skipws()) == ',');    /* Get another argument */
  110.             if (c != ')')                       /* Must end at )        */
  111.                 goto bad_define;
  112.             c = ' ';                            /* Will skip to body    */
  113.         }
  114.         else {
  115.             /*
  116.              * DEF_NOARGS is needed to distinguish between
  117.              * "#define foo" and "#define foo()".
  118.              */
  119.             nargs = DEF_NOARGS;                 /* No () parameters     */
  120.         }
  121.         if (type[c] == SPA)                     /* At whitespace?       */
  122.             c = skipws();                       /* Not any more.        */
  123.         workp = work;                           /* Replacement put here */
  124.         inmacro = TRUE;                         /* Keep \<newline> now  */
  125.         for (; c != EOF_CHAR && c != '\n'; c = get()) {
  126. #if OK_CONCAT != CON_FALSE
  127.             if (c == '#') {                     /* String/concat?       */
  128.                 if ((c = get()) == '#') {       /* Concatenate tokens?  */
  129.                     while (workp > work && type[workp[-1]] == SPA)
  130.                         --workp;                /* Erase leading spaces */
  131.                     save(SEP);
  132.                     c = skipws();               /* Eat whitespace       */
  133.                     switch (type[c]) {          /* What flavor of token */
  134.                     case LET:
  135.                         checkparm(c, dp);       /* Save it normally     */
  136.                         break;
  137.  
  138.                     case DIG:
  139.                         do {                    /* Stuff the digits     */
  140.                             save(c);
  141.                             c = get();
  142.                         } while (type[c] == DIG);
  143.                         break;
  144.  
  145.                     default:
  146.                         ciwarn("Strange character after # (%d.)", c);
  147.                         save(c);
  148.                         break;
  149.                     }
  150.                     save(SEP);                  /* Delimit 2nd token    */
  151.                 }
  152.                 else {                          /* Stringize            */
  153.                     unget();                    /* Gotta rescan it      */
  154.                     /*
  155.                      * We store a magic cookie (which becomes " on output)
  156.                      * so the macro expander doesn't block expansion
  157.                      * of the actual parameter.  For example,
  158.                      *          #define abc(a) #a
  159.                      *          abc(__LINE__)
  160.                      * should yield "123", not "__LINE__".
  161.                      * This is a hack, and probably going to cause trouble.
  162.                      */
  163.                     save(ST_QUOTE);
  164.                     if ((c = isformal(skipws())) == 0) {
  165.                         cwarn("Expected formal parameter, got \"%s\"", token);
  166.                         mtokensave(dp);
  167.                     }
  168.                     save(ST_QUOTE);
  169.                 }
  170.                 continue;                       /* Done with this token */
  171.             }
  172. #endif
  173.             switch (type[c]) {
  174.             case LET:
  175.                 checkparm(c, dp);               /* Might be a formal    */
  176.                 break;
  177.  
  178.             case DIG:                           /* Number in mac. body  */
  179.             case DOT:                           /* Maybe a float number */
  180.                 scannumber(c, save);            /* Scan it off          */
  181.                 break;
  182.  
  183.             case QUO:                           /* String in mac. body  */
  184. #if STRING_FORMAL
  185.                 stparmscan(c, dp);              /* Do string magic      */
  186. #else
  187.                 stparmscan(c);
  188. #endif
  189.                 break;
  190.  
  191.             case BSH:                           /* Backslash            */
  192.                 save('\\');
  193.                 if ((c = get()) == '\n')
  194.                     wrongline = TRUE;
  195.                 save(c);
  196.                 break;
  197.  
  198.             case SPA:                           /* Absorb whitespace    */
  199.                 /*
  200.                  * Note: the "end of comment" marker is passed on
  201.                  * to allow comments to separate tokens.
  202.                  */
  203.                 if (workp[-1] == ' ')           /* Absorb multiple      */
  204.                     break;                      /* spaces               */
  205.                 else if (c == '\t')
  206.                     c = ' ';                    /* Normalize tabs       */
  207.                 /* Fall through to store character                      */
  208.             default:                            /* Other character      */
  209.                 save(c);
  210.                 break;
  211.             }
  212.         }
  213.         inmacro = FALSE;                        /* Stop newline hack    */
  214.         unget();                                /* For control check    */
  215.         if (workp > work && workp[-1] == ' ')   /* Drop trailing blank  */
  216.             workp--;
  217.         *workp = EOS;                           /* Terminate work       */
  218.         dp->repl = savestring(work);            /* Save the string      */
  219.         dp->nargs = nargs;                      /* Save arg count       */
  220. #if DEBUG
  221.         if (debug)
  222.             dumpadef("macro definition", dp);
  223. #endif
  224.         if (isredefine) {                       /* Error if redefined   */
  225.             if ((old != NULL && dp->repl != NULL && !streq(old, dp->repl))
  226.              || (old == NULL && dp->repl != NULL)
  227.              || (old != NULL && dp->repl == NULL)) {
  228.                 cerror("Redefining defined variable \"%s\"", dp->name);
  229.             }
  230.             if (old != NULL)                    /* We don't need the    */
  231.                 free(old);                      /* old definition now.  */
  232.         }
  233.         return;
  234.  
  235. bad_define:
  236.         cerror("#define syntax error", NULLST);
  237.         inmacro = FALSE;                        /* Stop <newline> hack  */
  238. }
  239.  
  240.  
  241.  
  242.  
  243.  
  244.  
  245.  
  246.  
  247. checkparm(c, dp)
  248. register int    c;
  249. DEFBUF          *dp;
  250. /*
  251.  * Replace this param if it's defined.  Note that the macro name is a
  252.  * possible replacement token.  We stuff DEF_MAGIC in front of the token
  253.  * which is treated as a LETTER by the token scanner and eaten by
  254.  * the output routine.  This prevents the macro expander from
  255.  * looping if someone writes "#define foo foo".
  256.  */
  257. {
  258.         if ((c = isformal(c)) == 0)
  259.             mtokensave(dp);
  260. }
  261.  
  262. FILE_LOCAL int
  263. isformal(c)
  264. register int    c;
  265. /*
  266.  * Scan the token starting with c.  If it is a formal parameter, save
  267.  * the MAC_PARM and formal offset, returning TRUE.  Else, return FALSE.
  268.  */
  269. {
  270.         register int    i;
  271.  
  272.         scanid(c);                              /* Get parm to token[]  */
  273.         for (i = 0; i < nargs; i++) {           /* For each argument    */
  274.             if (streq(parlist[i], token)) {     /* If it's known        */
  275.                 save(MAC_PARM);                 /* Save the signal      */
  276.                 save(i + 1);                    /* Save the formal      */
  277.                 return (TRUE);                  /* Return "gotcha"      */
  278.             }
  279.         }
  280.         return (FALSE);                         /* Not a formal param   */
  281. }
  282.  
  283. FILE_LOCAL
  284. mtokensave(dp)
  285. DEFBUF          *dp;
  286. /*
  287.  * Save the token in the macro buffer.  A magic cookie is saved
  288.  * if the token is identical to the macro name, so the expansion
  289.  * doesn't recurse.
  290.  */
  291. {
  292.         register char           *cp;
  293.  
  294.         if (dp != NULL && streq(dp->name, token)) /* Macro name in body */
  295.             save(DEF_MAGIC);                    /* Save magic marker    */
  296.         for (cp = token; *cp != EOS;)           /* And save             */
  297.             save(*cp++);                        /* The token itself     */
  298. }
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  305.  
  306.  
  307.  
  308.  
  309.  
  310.  
  311.  
  312.  
  313.  
  314.  
  315.  
  316.  
  317.  
  318.  
  319. #if STRING_FORMAL
  320. stparmscan(delim, dp)
  321. int             delim;
  322. register DEFBUF *dp;
  323. /*
  324.  * Scan the string (starting with the given delimiter).
  325.  * The token is replaced if it is the only text in this string or
  326.  * character constant.  The algorithm follows checkparm() above.
  327.  * Note that scanstring() has approved of the string.
  328.  */
  329. {
  330.         register int            c;
  331.  
  332.         /*
  333.          * Warning -- this code hasn't been tested for a while.
  334.          * It exists only to preserve compatibility with earlier
  335.          * implementations of cpp.  It is not part of the Draft
  336.          * ANSI Standard C language.
  337.          */
  338.         save(delim);
  339.         instring = TRUE;
  340.         while ((c = get()) != delim
  341.              && c != '\n'
  342.              && c != EOF_CHAR) {
  343.             if (type[c] == LET)                 /* Maybe formal parm    */
  344.                 checkparm(c, (DEFBUF *) NULL);  /* But no DEF_MAGIC     */
  345.             else {
  346.                 save(c);
  347.                 if (c == '\\')
  348.                     save(get());
  349.             }
  350.         }
  351.         instring = FALSE;
  352.         if (c != delim)
  353.             cerror("Unterminated string in macro body", NULLST);
  354.         save(c);
  355. }
  356. #else
  357. stparmscan(delim)
  358. int             delim;
  359. /*
  360.  * Normal string parameter scan.
  361.  */
  362. {
  363.         register char           *wp;
  364.         register int            i;
  365.         extern int              save();
  366.  
  367.         wp = workp;                     /* Here's where it starts       */
  368.         if (!scanstring(delim, save))
  369.             return;                     /* Exit on scanstring error     */
  370. #if 0 && STRING_FORMAL
  371.         /*
  372.          * This code -- if reenabled -- recognizes a formal parameter
  373.          * if it is the only component of a string:
  374.          *      #define foo(bar, v) printf("%" "bar" "\n", v);
  375.          * This has been superceded by # stringizing.
  376.          */
  377.         workp[-1] = EOS;                /* Erase trailing quote         */
  378.         wp++;                           /* -> first string content byte */
  379. #if (NMACPARS * 2) + 1 > 255
  380.     << error, the following won't work >>
  381. #endif
  382.         for (i = 0; i < nargs; i++) {
  383.             if (streq(parlist[i], wp)) {
  384.                 *wp++ = MAC_PARM;               /* Parameter signal     */
  385.                 *wp++ = i + NMACPARS + 1;       /* Out of range marker  */
  386.                 *wp = wp[-3];                   /* Add on closing quote */
  387.                 workp = wp + 1;                 /* Reset string end     */
  388.                 return;
  389.             }
  390.         }
  391.         workp[-1] = wp[-1];             /* Nope, reset end quote.       */
  392. #endif
  393. }
  394. #endif
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402.  
  403.  
  404.  
  405.  
  406.  
  407.  
  408.  
  409.  
  410.  
  411.  
  412.  
  413.  
  414.  
  415. doundef()
  416. /*
  417.  * Remove the symbol from the defined list.
  418.  * Called from the #control processor.
  419.  */
  420. {
  421.         register int            c;
  422.  
  423.         if (type[(c = skipws())] != LET)
  424.             cerror("Illegal #undef argument", NULLST);
  425.         else {
  426.             scanid(c);                          /* Get name to token[]  */
  427.             if (defendel(token, TRUE) == NULL) {
  428.                 cwarn("Symbol \"%s\" not defined in #undef", token);
  429.             }
  430.         }
  431. }
  432.  
  433. textput(text)
  434. char            *text;
  435. /*
  436.  * Put the string in the parm[] buffer.
  437.  */
  438. {
  439.         register int    size;
  440.  
  441.         size = strlen(text) + 1;
  442.         if ((parmp + size) >= &parm[NPARMWORK])
  443.             cfatal("Macro work area overflow", NULLST);
  444.         else {
  445.             strcpy(parmp, text);
  446.             parmp += size;
  447.         }
  448. }
  449.  
  450. charput(c)
  451. register int    c;
  452. /*
  453.  * Put the byte in the parm[] buffer.
  454.  */
  455. {
  456.         if (parmp >= &parm[NPARMWORK])
  457.             cfatal("Macro work area overflow", NULLST);
  458.         else {
  459.             *parmp++ = c;
  460.         }
  461. }
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.  
  469.  
  470.  
  471.  
  472.  
  473.  
  474.  
  475.  
  476.  
  477.  
  478.  
  479.  
  480.  
  481.  
  482.  
  483.  
  484.  
  485.  
  486.  
  487. /*
  488.  *              M a c r o   E x p a n s i o n
  489.  */
  490.  
  491. static DEFBUF   *macro;         /* Catches start of infinite macro      */
  492.  
  493. expand(tokenp)
  494. register DEFBUF *tokenp;
  495. /*
  496.  * Expand a macro.  Called from the cpp mainline routine (via subroutine
  497.  * macroid()) when a token is found in the symbol table.  It calls
  498.  * expcollect() to parse actual parameters, checking for the correct number.
  499.  * It then creates a "file" containing a single line containing the
  500.  * macro with actual parameters inserted appropriately.  This is
  501.  * "pushed back" onto the input stream.  (When the get() routine runs
  502.  * off the end of the macro line, it will dismiss the macro itself.)
  503.  */
  504. {
  505.         register int            c;
  506.         register FILEINFO       *file;
  507.         extern FILEINFO         *getfile();
  508.  
  509. #if DEBUG
  510.         if (debug) {
  511.             dumpadef("expand entry", tokenp);
  512.             dumpunget("expand entry");
  513.         }
  514. #endif
  515.         /*
  516.          * If no macro is pending, save the name of this macro
  517.          * for an eventual error message.
  518.          */
  519.         if (recursion++ == 0)
  520.             macro = tokenp;
  521.         else if (recursion == RECURSION_LIMIT) {
  522.             cerror("Recursive macro definition of \"%s\"", tokenp->name);
  523.             fprintf(stderr, "(Defined by \"%s\")\n", macro->name);
  524.             if (rec_recover) {
  525.                 do {
  526.                     c = get();
  527.                 } while (infile != NULL && infile->fp == NULL);
  528.                 unget();
  529.                 recursion = 0;
  530.                 return;
  531.             }
  532.         }
  533.         /*
  534.          * Here's a macro to expand.
  535.          */
  536.         nargs = 0;                              /* Formals counter      */
  537.         parmp = parm;                           /* Setup parm buffer    */
  538.         switch (tokenp->nargs) {
  539.         case (-2):                              /* __LINE__             */
  540.             sprintf(work, "%d", line);
  541.             ungetstring(work);
  542.             break;
  543.  
  544.         case (-3):                              /* __FILE__             */
  545.             for (file = infile; file != NULL; file = file->parent) {
  546.                 if (file->fp != NULL) {
  547.                     sprintf(work, "\"%s\"", (file->progname != NULL)
  548.                         ? file->progname : file->filename);
  549.                     ungetstring(work);
  550.                     break;
  551.                 }
  552.             }
  553.             break;
  554.  
  555.         default:
  556.             /*
  557.              * Nothing funny about this macro.
  558.              */
  559.             if (tokenp->nargs < 0)
  560.                 cfatal("Bug: Illegal __ macro \"%s\"", tokenp->name);
  561.             while ((c = skipws()) == '\n')      /* Look for (, skipping */
  562.                 wrongline = TRUE;               /* spaces and newlines  */
  563.             if (c != '(') {
  564.                 /*
  565.                  * If the programmer writes
  566.                  *      #define foo() ...
  567.                  *      ...
  568.                  *      foo [no ()]
  569.                  * just write foo to the output stream.
  570.                  */
  571.                 unget();
  572.                 cwarn("Macro \"%s\" needs arguments", tokenp->name);
  573.                 fputs(tokenp->name, stdout);
  574.                 return;
  575.             }
  576.             else if (expcollect()) {            /* Collect arguments    */
  577.                 if (tokenp->nargs != nargs) {   /* Should be an error?  */
  578.                     cwarn("Wrong number of macro arguments for \"%s\"",
  579.                         tokenp->name);
  580.                 }
  581. #if DEBUG
  582.                 if (debug)
  583.                     dumpparm("expand");
  584. #endif
  585.             }                           /* Collect arguments            */
  586.         case DEF_NOARGS:                /* No parameters just stuffs    */
  587.             expstuff(tokenp);           /* Do actual parameters         */
  588.         }                               /* nargs switch                 */
  589. #if DEBUG
  590.         if (debug)
  591.             dumpunget("expand exit");
  592. #endif
  593. }
  594.  
  595.  
  596.  
  597.  
  598.  
  599.  
  600.  
  601.  
  602.  
  603.  
  604.  
  605.  
  606.  
  607. FILE_LOCAL int
  608. expcollect()
  609. /*
  610.  * Collect the actual parameters for this macro.  TRUE if ok.
  611.  */
  612. {
  613.         register int    c;
  614.         register int    paren;                  /* For embedded ()'s    */
  615.         extern int      charput();
  616.  
  617.         for (;;) {
  618.             paren = 0;                          /* Collect next arg.    */
  619.             while ((c = skipws()) == '\n')      /* Skip over whitespace */
  620.                 wrongline = TRUE;               /* and newlines.        */
  621.             if (c == ')') {                     /* At end of all args?  */
  622.                 /*
  623.                  * Note that there is a guard byte in parm[]
  624.                  * so we don't have to check for overflow here.
  625.                  */
  626.                 *parmp = EOS;                   /* Make sure terminated */
  627.                 break;                          /* Exit collection loop */
  628.             }
  629.             else if (nargs >= NMACPARS)         /* Should be an error   */
  630.                 cfatal("Too many actual parameters in macro expansion", NULLST);            parlist[nargs++] = parmp;           /* At start of new arg  */
  631.             for (;; c = cget()) {               /* Collect arg's bytes  */
  632.                 if (c == EOF_CHAR) {
  633.                     cerror("end of file within macro argument", NULLST);
  634.                     return (FALSE);             /* Sorry.               */
  635.                 }
  636.                 else if (c == '\\') {           /* Quote next character */
  637.                     charput(c);                 /* Save the \ for later */
  638.                     charput(cget());            /* Save the next char.  */
  639.                     continue;                   /* And go get another   */
  640.                 }
  641.                 else if (type[c] == QUO) {      /* Start of string?     */
  642.                     scanstring(c, charput);     /* Scan it off          */
  643.                     continue;                   /* Go get next char     */
  644.                 }
  645.                 else if (c == '(')              /* Worry about balance  */
  646.                     paren++;                    /* To know about commas */
  647.                 else if (c == ')') {            /* Other side too       */
  648.                     if (paren == 0) {           /* At the end?          */
  649.                         unget();                /* Look at it later     */
  650.                         break;                  /* Exit arg getter.     */
  651.                     }
  652.                     paren--;                    /* More to come.        */
  653.                 }
  654.                 else if (c == ',' && paren == 0) /* Comma delimits args */
  655.                     break;
  656.                 else if (c == '\n')             /* Newline inside arg?  */
  657.                     wrongline = TRUE;           /* We'll need a #line   */
  658.                 charput(c);                     /* Store this one       */
  659.             }                                   /* Collect an argument  */
  660.             charput(EOS);                       /* Terminate argument   */
  661. #if DEBUG
  662.             if (debug)
  663.                 printf("parm[%d] = \"%s\"\n", nargs, parlist[nargs - 1]);
  664. #endif
  665.         }                                       /* Collect all args.    */
  666.         return (TRUE);                          /* Normal return        */
  667. }
  668.  
  669.  
  670.  
  671.  
  672.  
  673.  
  674.  
  675.  
  676.  
  677.  
  678. FILE_LOCAL
  679. expstuff(tokenp)
  680. DEFBUF          *tokenp;                /* Current macro being expanded */
  681. /*
  682.  * Stuff the macro body, replacing formal parameters by actual parameters.
  683.  */
  684. {
  685.         register int    c;                      /* Current character    */
  686.         register char   *inp;                   /* -> repl string       */
  687.         register char   *defp;                  /* -> macro output buff */
  688.         int             size;                   /* Actual parm. size    */
  689.         char            *defend;                /* -> output buff end   */
  690. #if 0 && STRING_FORMAL
  691.         int             string_magic;           /* String formal hack   */
  692. #endif
  693.         FILEINFO        *file;                  /* Funny #include       */
  694.         extern FILEINFO *getfile();
  695.  
  696.         file = getfile(NBUFF, tokenp->name);
  697.         inp = tokenp->repl;                     /* -> macro replacement */
  698.         defp = file->buffer;                    /* -> output buffer     */
  699.         defend = defp + (NBUFF - 1);            /* Note its end         */
  700.         if (inp != NULL) {
  701.             while ((c = (*inp++ & 0xFF)) != EOS) {
  702.                 if (c == MAC_PARM) {
  703.                     c = (*inp++ & 0xFF) - 1;    /* Parm number          */
  704. #if 0 && STRING_FORMAL
  705.                     string_magic = ((c >= NMACPARS) != 0);
  706.                     if (string_magic)
  707.                         c -= NMACPARS;
  708. #endif
  709.                     /*
  710.                      * Replace formal parameter by actual parameter string.
  711.                      */
  712.                     if (c < nargs) {
  713.                         size = strlen(parlist[c]);
  714.                         if ((defp + size) >= defend)
  715.                             goto nospace;
  716. #if 0 && STRING_FORMAL
  717.                         /*
  718.                          * Erase the extra set of quotes.
  719.                          */
  720.                         if (string_magic && defp[-1] == parlist[c][0]) {
  721.                             strcpy(defp-1, parlist[c]);
  722.                             defp += (size - 2);
  723.                         }
  724.                         else {
  725.                             strcpy(defp, parlist[c]);
  726.                             defp += size;
  727.                         }
  728. #else
  729.                         strcpy(defp, parlist[c]);
  730.                         defp += size;
  731. #endif
  732.                     }
  733.                 }
  734.                 else if (defp >= defend) {
  735. nospace:            cfatal("Out of space in macro \"%s\" arg expansion",
  736.                         tokenp->name);
  737.                 }
  738.                 else {
  739.                     *defp++ = c;
  740.                 }
  741.             }
  742.         }
  743.         *defp = EOS;
  744. #if DEBUG
  745.         if (debug > 1)
  746.             printf("macroline: \"%s\"\n", file->buffer);
  747. #endif
  748. }
  749.  
  750.  
  751.  
  752.  
  753.  
  754.  
  755.  
  756.  
  757.  
  758.  
  759.  
  760.  
  761.  
  762.  
  763.  
  764.  
  765.  
  766.  
  767.  
  768.  
  769.  
  770.  
  771.  
  772.  
  773.  
  774. #if DEBUG
  775. dumpparm(why)
  776. char            *why;
  777. /*
  778.  * Dump parameter list.
  779.  */
  780. {
  781.         register int    i;
  782.  
  783.         printf("dump of %d parameters (%d bytes total) %s\n",
  784.             nargs, parmp - parm, why);
  785.         for (i = 0; i < nargs; i++) {
  786.             printf("parm[%d] (%d) = \"%s\"\n",
  787.                 i + 1, strlen(parlist[i]), parlist[i]);
  788.         }
  789. }
  790. #endif
  791.  
  792.